package com.alinesno.cloud.base.workflow.activiti.controller;

import com.alinesno.cloud.base.workflow.activiti.WorkFlowService;
import com.alinesno.cloud.base.workflow.activiti.model.ActivitiModel;
import com.alinesno.cloud.common.core.page.DatatablesPageBean;
import com.alinesno.cloud.common.core.response.ResponseBean;
import com.alinesno.cloud.common.core.response.ResponseGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;

/**
 * Activiti工作流模型操作
 * 
 * @author LuoAnDong
 * @since 2019年9月1日 下午4:24:50
 */
@RestController
@RequestMapping(value = "/activiti/module")
public class ActivitiModuleController {

	private static final Logger log = LoggerFactory.getLogger(ActivitiModuleController.class);

	@Autowired
	private RepositoryService repositoryService;

	@Autowired
	private WorkFlowService workFlowService; 

	@ResponseBody
	@RequestMapping(value = "/test")
	public String test() {
		return "SUCCESS";
	}

	/**
	 * 创建模型
	 * 
	 * @param request
	 * @param model
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping("/create")
	public void create(HttpServletRequest request, ActivitiModel model, HttpServletResponse response)
			throws IOException {
		String modelId = workFlowService.createModel(model); ; 
		response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + modelId);
	}

	/**
	 * 批量删除
	 * 
	 * @param ids
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "delete")
	@ResponseBody
	public ResponseBean deleteByIds(String[] ids, HttpServletRequest request) {
		for (String id : ids) {
			repositoryService.deleteModel(id);
		}
		return ResponseGenerator.ok("删除成功.");
	}
	
	/**
     *  启动流程
     */
    @RequestMapping("/start")
    @ResponseBody
    public ResponseBean startProcess(String keyName) {
        ProcessInstance process = workFlowService.getRuntimeService().startProcessInstanceByKey(keyName);
        //  return process.getId() + " : " + process.getProcessDefinitionId();
		return ResponseGenerator.ok(process.getId()) ; //"删除成功.");
    }
    
    /**
     *  提交任务
     */
    @RequestMapping("/run")
    @ResponseBody
    public ResponseBean run(String processInstanceId) {
        Task task = workFlowService.getTaskService().createTaskQuery().processInstanceId(processInstanceId).singleResult();
        log.info("task {} find ", task.getId());
        workFlowService.getTaskService().complete(task.getId());
        
		return ResponseGenerator.ok("删除成功.");
    }


	/**
	 * 编辑模型
	 * <a class="btn btn-success" href="/ActivitiDemo5/service/editor?id='+row.id+'"
	 * target="_blank">编辑</a>
	 * 
	 * @param ids
	 * @param request
	 * @return
	 * @throws IOException 
	 */
	@RequestMapping(value = "editor")
	public void editorModule(String id, HttpServletResponse response , HttpServletRequest request) throws IOException {
		log.debug("id:{}", id);
		response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + id) ; //modelData.getId());
	}

	/**
	 * 导出model的xml文件
	 */
	@RequestMapping(value = "export/{modelId}")
	public void export(@PathVariable("modelId") String modelId, HttpServletResponse response) {
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		try {
			Model modelData = repositoryService.getModel(modelId);
			BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
			// 获取节点信息
			byte[] arg0 = repositoryService.getModelEditorSource(modelData.getId());
			JsonNode editorNode = new ObjectMapper().readTree(arg0);

			// 将节点信息转换为xml
			BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
			BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
			byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);

			ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
			IOUtils.copy(in, response.getOutputStream());

			String filename = modelData.getName() + ".bpmn20.xml";
			response.setHeader("Content-Disposition","attachment; filename=" + java.net.URLEncoder.encode(filename, "UTF-8"));
			response.flushBuffer();
		} catch (Exception e) {
			PrintWriter out = null;
			try {
				out = response.getWriter();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			out.write("未找到对应数据");
			e.printStackTrace();
		}
	}

	/**
	 * 部署
	 */
	@RequestMapping(value = "deploy", method = RequestMethod.POST)
	@ResponseBody
	public ResponseBean deploy(@RequestParam("modelId") String modelId, HttpServletRequest request) {
		try {
			Model modelData = repositoryService.getModel(modelId);
			ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
			byte[] bpmnBytes = null;
			BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
			bpmnBytes = new BpmnXMLConverter().convertToXML(model);
			
			String processName = modelData.getName() + ".bpmn20.xml";
			
			log.debug("modelData:{}" , ToStringBuilder.reflectionToString(modelData));
			
			Deployment deployment = repositoryService.createDeployment()
						.name(modelData.getName())
						.addString(processName, new String(bpmnBytes, "utf-8"))
						.deploy();

			log.debug("deployment:{}", deployment);

			return ResponseGenerator.ok("部署成功.");
		} catch (Exception e) {
			log.error("流程【{}】部署失败:{}", modelId, e);
			return ResponseGenerator.fail("部署失败.");
		}
	}

	@RequestMapping(value = "workflowImage", method = RequestMethod.GET)
	public String workflowImage(HttpServletResponse response , String deploymentId) throws IOException {
		log.debug("deploymentId:{}" , deploymentId);
		
		//获取图片资源名称
        List<String> list = workFlowService.getRepositoryService().getDeploymentResourceNames(deploymentId);
        //定义图片资源的名称
        String resourceName = "";
        if(list!=null && list.size()>0){
            for(String name:list){
                if(name.indexOf(".png")>=0){
                    resourceName = name;
                }
            }
        }
		
		InputStream in = repositoryService.getResourceAsStream(deploymentId, resourceName) ; 
		OutputStream out = response.getOutputStream();
		
		// 把图片的输入流程写入resp的输出流中
		byte[] b = new byte[1024];
		for (int len = -1; (len = in.read(b)) != -1;) {
			out.write(b, 0, len);
		}
		
		IOUtils.write(b, out); 
		return null ; 
	}

	/**
	 * 查询户端分页
	 * 
	 * @return
	 */
	@ResponseBody
	@PostMapping("/datatables")
	public DatatablesPageBean datatables(HttpServletRequest request, Model model, DatatablesPageBean page) {
		log.debug("page = {}", ToStringBuilder.reflectionToString(page));

		ModelQuery query = repositoryService.createModelQuery().orderByCreateTime().desc();
		List<Model> list = query.listPage((page.getPageNum() - 1) * page.getPageSize(), page.getPageSize());

		page.setRows(list);
		page.setTotal((int) query.count());
		page.setCode(HttpStatus.OK.value());

		return page;
	}

}
